package com.quyunshuo.module.home.view

import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import android.view.animation.DecelerateInterpolator
import androidx.core.content.withStyledAttributes
import com.quyunshuo.module.home.R

@SuppressLint("Recycle", "DrawAllocation")
class CircleProgressView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    // 背景圆的画笔
    private val backgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        style = Paint.Style.STROKE
    }

    // 进度弧线的画笔
    private val progressPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        style = Paint.Style.STROKE
        strokeCap = Paint.Cap.ROUND // 进度条两端为圆角
    }

    // 绘制区域矩形
    private val oval = RectF()

    // 当前进度 (0-100)
    private var progress = 0f
        set(value) {
            field = value.coerceIn(0f, 100f)
            invalidate()
        }

    // 进度条宽度
    private var strokeWidth = 15f

    // 进度条起始角度（从12点方向开始）
    private val startAngle = -90f

    // 动画持续时间
    private val animationDuration = 1000L

    // 默认颜色值
    private var defaultBackgroundColor = Color.LTGRAY
    private var defaultProgressColor = Color.BLUE

    init {
        // 初始化画笔默认值
        backgroundPaint.color = defaultBackgroundColor  // 设置背景圆的默认颜色
        backgroundPaint.strokeWidth = strokeWidth  // 设置背景圆的默认线条宽度

        progressPaint.color = defaultProgressColor  // 设置进度条的默认颜色
        progressPaint.strokeWidth = strokeWidth  // 设置进度条的默认线条宽度

        // 处理XML中定义的自定义属性
        context.withStyledAttributes(attrs, R.styleable.CircleProgressView) {
            // 获取XML中设置的背景颜色，如果没有设置则使用默认值
            backgroundPaint.color = getColor(
                R.styleable.CircleProgressView_backgroundColor,
                defaultBackgroundColor
            )

            // 获取XML中设置的进度条颜色，如果没有设置则使用默认值
            progressPaint.color = getColor(
                R.styleable.CircleProgressView_progressColor,
                defaultProgressColor
            )

            // 获取XML中设置的线条宽度（通常以dp为单位）
            strokeWidth = getDimension(
                R.styleable.CircleProgressView_strokeWidth,
                strokeWidth
            )

            // 将新的线条宽度应用到背景圆画笔
            backgroundPaint.strokeWidth = strokeWidth
            // 将新的线条宽度应用到进度条画笔
            progressPaint.strokeWidth = strokeWidth

            // 获取XML中设置的初始进度值（0-100）
            progress = getFloat(R.styleable.CircleProgressView_progress, 0f)
        }
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)  // 调用父类测量方法

        // 确保视图为正方形（取宽高中较小者）
        val width = MeasureSpec.getSize(widthMeasureSpec)  // 获取测量模式建议的宽度
        val height = MeasureSpec.getSize(heightMeasureSpec)  // 获取测量模式建议的高度
        val size = width.coerceAtMost(height)  // 取宽度和高度的最小值

        // 设置视图的实际尺寸（正方形）
        setMeasuredDimension(size, size)
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)  // 调用父类方法处理尺寸变化

        // 计算绘制的矩形区域，需要考虑线条宽度的影响
        val padding = strokeWidth / 2  // 内边距（确保完整显示线条）

        // 设置绘制区域（留出内边距，避免线条被裁剪）
        oval.set(
            padding,     // 左边界 = 内边距
            padding,     // 上边界 = 内边距
            w - padding, // 右边界 = 宽度 - 内边距
            h - padding  // 下边界 = 高度 - 内边距
        )
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)  // 调用父类绘制方法

        // 1. 绘制背景圆（圆形轮廓）
        canvas.drawOval(oval, backgroundPaint)
        /*
            为什么要除以100？：progress 是当前的进度值，通常范围是0-100（百分比）     除以100是为了将整数的百分比转换为小数（0.0-1.0）
            为什么要乘以360？：360表示一个完整的圆周（360度）   乘以360是为了将比例转换为实际的角度值
         */
        // 2. 绘制进度弧线（从12点位置开始，顺时针方向）
        val sweepAngle = (progress / 100f) * 360f  // 计算弧度角度（0-100映射到0-360度）

        // 绘制弧线：
        // - oval：绘制的矩形区域
        // - startAngle: -90度（从12点位置开始）
        // - sweepAngle: 进度对应的弧度
        // - false: 不绘制到中心点的连线（只是弧线）
        // - progressPaint: 使用进度条画笔
        /* todo
            为什么以前是写x轴的位置，y轴的位置，到了drawArc，就写-90这些度数呢？
            1. 笛卡尔坐标系 (Cartesian Coordinate System)

            ​​特征​​：
                使用水平方向 (x) 和垂直方向 (y) 描述位置
                用于绘制点、线、矩形等基本图形
                示例：canvas.drawCircle(x, y, radius, paint)
           2. 极坐标系 (Polar Coordinate System)

            ​​特征​​：
                使用半径 (r) 和角度 (θ) 描述位置
                用于描述圆形相关的几何图形
                数学表达式：(x = r × cos(θ), y = r × sin(θ))

            圆形没有"起点"的概念，但角度系统提供了描述圆周上位置的统一方式
            角度系统简化了圆周等分的描述：
                四等分：0°, 90°, 180°, 270°
                十二等分：每个小时的位置

        【也就是底层还是x轴和y轴，只不过drawArc封装成了角度，让我们更见方便的使用，对吗？对的，底层绘制始终基于笛卡尔坐标系（x,y），但 drawArc 提供了更高级的抽象，让我们能够用角度来描述圆形图形。】

         */
        canvas.drawArc(oval, startAngle, sweepAngle, false, progressPaint)
    }

    /**
     * 设置进度
     * @param newProgress 0-100之间的值
     * @param animate 是否使用动画过渡
     */
    fun setProgress(newProgress: Float, animate: Boolean = true) {
        val targetProgress = newProgress.coerceIn(0f, 100f)
        
        if (animate) {
            ValueAnimator.ofFloat(progress, targetProgress).apply {
                duration = animationDuration
                interpolator = DecelerateInterpolator()
                addUpdateListener { animator ->
                    progress = animator.animatedValue as Float
                }
                start()
            }
        } else {
            progress = targetProgress
        }
    }


}